package game;
import java.awt.Point;
import java.util.Iterator;
import java.util.List;
import java.util.LinkedList;
import java.util.Observable;

public class GameEngine extends Observable {
	
	/**Constant representing an empty space.*/
	public static final int EMPTY = 0;
	/**Constant representing a light single man.*/
	public static final int LIGHT = 1;
	/**Constant representing a light king.*/
	public static final int LIGHT_KING = 2;
	/**Constant represenging a dark single man.*/
	public static final int DARK = 3;
	/**Constant representing a dark king.*/
	public static final int DARK_KING = 4;
	/** Constant representing a standard sized board. */
	public static final int STD_BOARD_SIZE = 8;

	/** Array used for the board positions: */
	private int[][] iBoard;

	/** The number of squares along one edge of the board:
		* (Board is currently assumed to be square) 
		*/
	private int iBoardSize;

	/** Change to true to activate debug code: */
	private boolean debug = true;

	/** Boolean to control the turn structure: */
	private boolean iDarkPlayerTurn;
        public boolean blockMove = false;

        public boolean isBlockMove() {
            return blockMove;
        }

        public void setBlockMove(boolean blockMove) {
            this.blockMove = blockMove;
        }
        
	/** If there is a move in progress that has not terminated
	after 1 move/jump sequence, this point holds the
	coordinates of the piece making the move.
	If not, this point contains null.
	*/
	private Point iMoveInProgress;

	/** Constructor.
	 * This constructor does not take the board size parameter into account.  
	 * All instances of this object have a board size of 8, i.e. 64 squares. 
	 * <br /><br />
	 * This size being the standard for most checker games.
	 */
	public GameEngine() {
		this(STD_BOARD_SIZE);
	}

	/**Constructor.
	 * This constructor takes the board size parameter into account. All instances of this 
	 * object have an equal square size,
	 * <br /><br />
	 * i.e. if <tt>boardSize</tt> = 5 than the board size is 25 squares.
	 * @param boardSize The size of the board to be created. Specified by the number of
	 * squares along one edge of the board.
		*/
	public GameEngine(int boardSize) {

		iBoardSize = boardSize;
		iDarkPlayerTurn = false;
		iBoard = new int[iBoardSize][iBoardSize];
		init();
		if (debug)
			System.out.println(this);   
                
	}

	/**Determines whether a piece at the specified coordinate is capable of
	   a single jump.
	   @param x The horizontal component of the coordinate.
	   @param y The vertical component of the coordinate.
	   @return True if the piece at the specified coordinate has a jump move available.
	   False if otherwise.
	*/
	public synchronized boolean canJump(int x, int y) {
		if (isEmpty(x, y) || isIllegalSpace(x, y)) {
			if (debug)
				System.out.println(
					" ("
						+ x
						+ ", "
						+ y
						+ ") cannot jump: Space is illegal or empty.");
			return false;
		} else if (isDark(x, y)) {
			if (isLight(x + 1, y + 1) && isEmpty(x + 2, y + 2)) {
				if (debug)
					System.out.println(" (" + x + ", " + y + ") can jump.");
				return true;
			}

			if (isLight(x - 1, y + 1) && isEmpty(x - 2, y + 2)) {
				if (debug)
					System.out.println(" (" + x + ", " + y + ") can jump.");
				return true;
			}

			if (isKing(x, y)
				&& isLight(x + 1, y - 1)
				&& isEmpty(x + 2, y - 2)) {
				if (debug)
					System.out.println(" (" + x + ", " + y + ") can jump.");
				return true;
			}

			if (isKing(x, y)
				&& isLight(x - 1, y - 1)
				&& isEmpty(x - 2, y - 2)) {
				if (debug)
					System.out.println(" (" + x + ", " + y + ") can jump.");
				return true;
			}

			if (debug)
				System.out.println(
					" (" + x + ", " + y + ") cannot jump: No jump available.");
			return false;
		} else if (isLight(x, y)) {
			if (isDark(x + 1, y - 1) && isEmpty(x + 2, y - 2)) {
				if (debug)
					System.out.println(" (" + x + ", " + y + ") can jump.");
				return true;
			}
			if (isDark(x - 1, y - 1) && isEmpty(x - 2, y - 2)) {
				if (debug)
					System.out.println(" (" + x + ", " + y + ") can jump.");
				return true;
			}
			if (isKing(x, y)
				&& isDark(x + 1, y + 1)
				&& isEmpty(x + 2, y + 2)) {
				if (debug)
					System.out.println(" (" + x + ", " + y + ") can jump.");
				return true;
			}
			if (isKing(x, y)
				&& isDark(x - 1, y + 1)
				&& isEmpty(x - 2, y + 2)) {
				if (debug)
					System.out.println(" (" + x + ", " + y + ") can jump.");
				return true;
			}

			if (debug)
				System.out.println(
					" (" + x + ", " + y + ") cannot jump: No jump available.");
			return false;
		}
		return false;
	}

	/**Determines whether a piece at the specified board coordinate is
	   capable of simple movement, excluding jumps. 
	   @param x The horizontal component of the coordinate.
	   @param y The vertical component of the coordinate.
	   @return True if the piece at the specified coordinate has a possible slide move.
	   False if otherwise.
	*/
	public synchronized boolean canSlide(int x, int y) {
		if (isEmpty(x, y) || isIllegalSpace(x, y)) {
			if (debug)
				System.out.println(
					" ("
						+ x
						+ ", "
						+ y
						+ ") cannot slide: Space is illegal or empty.");
			return false;
		}

		//Dark men move down, light men move up. Kings move in either direction.
		else if (
			(isDark(x, y) || isKing(x, y))
				&& (isEmpty(x + 1, y + 1) || isEmpty(x - 1, y + 1))) {
			if (debug)
				System.out.println(" (" + x + ", " + y + ") can slide.");
			return true;
		} else if (
			(isLight(x, y) || isKing(x, y))
				&& (isEmpty(x + 1, y - 1) || isEmpty(x - 1, y - 1))) {
			if (debug)
				System.out.println(" (" + x + ", " + y + ") can slide.");
			return true;
		}

		if (debug)
			System.out.println(
				" (" + x + ", " + y + ") cannot slide: No slide available.");
		return false;
	}

	/**Determines whether a piece at the specified board coordinate is capable
	   of either moving or jumping.
	   @param y The vertical component of the coordinate.
	   @return True if the piece at the specified coordinate has either a
	   slide or jump move available. False if otherwise.
	*/
	public synchronized boolean canMove(int x, int y) {
		return (canSlide(x, y) || canJump(x, y));
	}

	/**Checks whether the board is in a win state. 
	  @return - 0 if the game is not in a win state.
	  <br>- 1 if the dark player has won.
	  <br>- 2 if the light player has won.
	*/
	public synchronized int gameHasBeenWon() {
		if (iDarkPlayerTurn) {
			if (!darkCanMove())
				return 2;
			return 0;
		} else {
			if (!lightCanMove())
				return 1;
			return 0;
		}
	}

	/**Retrieves the size of the board. The board size is measured as the number
	   of squares down one side of the board.
	   @return The size of the board.
	*/
	public synchronized int getBoardSize() {
		return iBoardSize;
	}

	/**Provides a reference to a 2 dimensional array representation
	   of the current board state. 
	  @return A 2 dimensional array representing the current state of the board.
	 */
	public synchronized int[][] getBoardState() {
		int[][] tBoard = new int[iBoardSize][iBoardSize];
		System.arraycopy(iBoard, 0, tBoard, 0, iBoardSize);
		return tBoard;
	}

	/**Initialises the board for a new game.
	   The dark player is set as the first to move.
	*/
	public synchronized void init() {
		iMoveInProgress = null;
		for (int y = 0; y < iBoardSize; y++) {
			for (int x = 0; x < iBoardSize; x++) {
				if (x % 2 == y % 2) {

					if (y < 3)
						iBoard[x][y] = DARK;

					//Place light pieces at the bottom:
					if (y > 4)
						iBoard[x][y] = LIGHT;

				} else
					iBoard[x][y] = EMPTY;
			}
		}
		
		setChanged();
		notifyObservers();
	}

	/**Determines whether the piece at board coordinate (x, y) is dark.
	   If the coordinates do not exist on the board or are empty,
	   this method will return false.
	   @param x The horizontal component of the coordinate.
	   @param y The vertical component of the coordinate.
	   @return True if the piece at the specified coordinate is light.
	   False if otherwise.
	*/
	public synchronized boolean isDark(int x, int y) {
		try {
			return (
				iBoard[x - 1][y - 1] == DARK
					|| iBoard[x - 1][y - 1] == DARK_KING);
		} catch (Exception e) {
			return false;
		}
	}

	/**Determines whose turn it is.
	   @return True if the dark player is to play next. False if otherwise.*/
	public synchronized boolean isDarkPlayerTurn() {          
                return iDarkPlayerTurn;
           
	}
//        public synchronized void turnEnable() {
//            enable = true;
//	} 
//        public synchronized void turnDisable() {
//            enable = false;
//	}
	/**Switches the turn from the current player to their opponent.
	   
	*/
	public synchronized void switchPlayerTurn() {
		iDarkPlayerTurn = !iDarkPlayerTurn;
		if (debug) {
			if (isLightPlayerTurn())
				System.out.println("Light player turn.");
			else
				System.out.println("Dark player turn.");
		}
		setChanged();
		notifyObservers();
	}

	/**Determines whose turn it is.
	   @return True if the light player is to play next. False if otherwise.
	*/
	public synchronized boolean isLightPlayerTurn() {
                    return !iDarkPlayerTurn;
	}
        public void setPlayerTurn(boolean turnDarkPlayer)
        {
            iDarkPlayerTurn = turnDarkPlayer;
        }

	/**Determines whether the piece at board coordinate (x, y) is light.
	   If the coordinates do not exist on the board or are empty,
	   this method will return false.
	   @param x The horizontal component of the coordinate.
	   @param y The vertical component of the coordinate.
	   @return True if the piece at the specified coordinate is light.
	   False if otherwise.
	*/
	public synchronized boolean isLight(int x, int y) {
		try {
			return (
				iBoard[x - 1][y - 1] == LIGHT
					|| iBoard[x - 1][y - 1] == LIGHT_KING);
		} catch (Exception e) {
			return false;
		}
	}

	/**Determines whether the piece at board coordinate (x, y) is a king.
	   @param x The horizontal component of the coordinate.
	   @param y The vertical component of the coordinate.
	   @return True if the piece at the specified coordinate is a king.
	   False if otherwise.
	*/
	public synchronized boolean isKing(int x, int y) {
		try {
			return (
				iBoard[x - 1][y - 1] == DARK_KING
					|| iBoard[x - 1][y - 1] == LIGHT_KING);
		} catch (Exception e) {
			return false;
		}
	}

	/**Determines whether the piece as board coordinate (x, y) is a single man.
	   @param x The horizontal component of the coordinate.
	   @param y The vertical component of the coordinate.
	   @return True if the piece at the specified coordinate is a man
	   (i.e. not a king). False if otherwise.
	*/
	public synchronized boolean isMan(int x, int y) {
		try {
			return (
				iBoard[x - 1][y - 1] == DARK || iBoard[x - 1][y - 1] == LIGHT);
		} catch (Exception e) {
			return false;
		}
	}

	/**Determines whether the board coordinate (x, y) is vacant.
	   @param x The horizontal component of the coordinate.
	   @param y The vertical component of the coordinate.
	   @return True if the specified coordinate does not contain a piece.
	   False if otherwise.
	*/
	public synchronized boolean isEmpty(int x, int y) {
		try {
			return (iBoard[x - 1][y - 1] == EMPTY);
		} catch (Exception e) {
			return false;
		}
	}

	/**Determines whether the board coordinate (x, y) contains a piece.
	   @param x The horizontal component of the coordinate.
	   @param y The vertical component of the coordinate.
	   @return True if the specified coordinate contains a piece.
	   False if otherwise.
	*/
	public synchronized boolean isOccupied(int x, int y) {
		try {
			return (iBoard[x - 1][y - 1] != EMPTY);
		} catch (Exception e) {
			return false;
		}
	}

	/**Returns a string to represent the board state.

	   @return A string representing the current board state.
	*/
	public synchronized String toString() {
		String tOutput = "   1  2  3  4  5  6  7  8  \n\n";
		int tRow = 0;
		for (int y = 0; y < iBoardSize; y++) {
			tOutput += tRow + 1 + "  ";
			tRow++;
			for (int x = 0; x < iBoardSize; x++) {
				switch (iBoard[x][y]) {
					case LIGHT :
						{
							tOutput += "LL ";
							break;
						}
					case LIGHT_KING :
						{
							tOutput += "LK ";
							break;
						}
					case DARK :
						{
							tOutput += "DD ";
							break;
						}
					case DARK_KING :
						{
							tOutput += "DK ";
							break;
						}
					default :
						{
							tOutput += "-- ";
							break;
						}
				}
				if (x == iBoardSize - 1)
					tOutput += "\n";
			}
			tOutput += "\n";
		}

		return tOutput;

	}

	/**Method used to perform a move on the board. 
	   @param x1 The horizontal component of the coordinates containing the
	   piece to be moved.
	   @param y1 The vertical component of the coordinates containing the
	   piece to be moved.
	   @param x2 The horizontal component of the coordinates indicating the
	   prospective move.
	   @param y2 The vertical component of the coordinates indicating the
	   prospective move.
	   @return True if the move has been successfully made.
	   False if otherwise.
	*/
	public synchronized boolean makeMove(int x1, int y1, int x2, int y2) {
		if (debug)
			System.out.println(
				"makeMove executing ("
					+ x1
					+ ", "
					+ y1
					+ ") to ("
					+ x2
					+ ", "
					+ y2
					+ ")...");
		//Check that the first coordinate is valid, and refers to a piece of the correct colour:
		if (isIllegalSpace(x1, y1)
			|| isEmpty(x1, y1)
			|| (isLight(x1, y1) && isDarkPlayerTurn())
			|| (isDark(x1, y1) && isLightPlayerTurn())) {
			if (debug)
				System.out.println(
					"Move from  ("
						+ x1
						+ ", "
						+ y1
						+ ") to ("
						+ x2
						+ ", "
						+ y2
						+ ") has failed.");
			return false;
		}

		//The piece to be moved is valid. Retrieve the list of all pieces that must jump:
		List tJumpList = mustJump();

		//If this list is non-empty then a piece must jump. Check that the specified piece
		//is contained on the list:
		if (tJumpList.size() > 0) {
			boolean tFlag = false;
			Iterator tIterator = tJumpList.iterator();
			while (tIterator.hasNext()) {
				Point tPoint = (Point) tIterator.next();
				if (x1 == tPoint.getX() && y1 == tPoint.getY()) {
					if (debug)
						System.out.println(
							" Piece to be moved is contained on the jump list.");
					tFlag = true;
					break; //HERE IS THE PROBLEM!!!!!! (Probably...)
				}
			} //HERE?

			if (!tFlag) {
				if (debug)
					System.out.println(
						"Move from  ("
							+ x1
							+ ", "
							+ y1
							+ ") to ("
							+ x2
							+ ", "
							+ y2
							+ ") has failed: another piece on the board must jump.");
				return false;
			}

			//The piece is on the list. Check that the move to be made is a legal jump.
			if (!isLegalJump(x1, y1, x2, y2)) {
				if (debug)
					System.out.println(
						"Move from  ("
							+ x1
							+ ", "
							+ y1
							+ ") to ("
							+ x2
							+ ", "
							+ y2
							+ ") has failed: Not a legal move.");
				return false;
			}

			if (debug)
				System.out.println("Jump called from makeMove (587).");
			//The move is legal and contained on the list. Make it:
			jump(x1, y1, x2, y2);
			//If the piece now has a jump move accessible to it, the turn has not ended:
			if (canJump(x2, y2)) {
				iMoveInProgress = new Point(x2, y2);
				//In US rules, a piece with a move in progress cannot be in a position to be
				//crowned.
				setChanged();
				notifyObservers();
				if (debug)
					System.out.println("makeMove Successful!\n" + this +" \n");
				return true;
			} else {
				iMoveInProgress = null;
				//Will only crown the piece if it is in the correct location:
				crown(x2, y2);
				if (debug)
					System.out.println("makeMove Successful!\n" + this +" \n");
				switchPlayerTurn();
				return true;
			}

		}

		//If the list is empty then there are no possible jumps, and the move must be a slide. Check for a legal slide move:
		else if (isLegalSlide(x1, y1, x2, y2)) {
			//The move is legal. Make it:
			slide(x1, y1, x2, y2);
			//Will only crown the piece if it is in the correct location:
			crown(x2, y2);
			if (debug)
				System.out.println(
					"makeMove (slide) Successful!\n" + this +"\n");
			switchPlayerTurn();
			return true;
		}
		if (debug)
			System.out.println(
				"Move from  ("
					+ x1
					+ ", "
					+ y1
					+ ") to ("
					+ x2
					+ ", "
					+ y2
					+ ") has failed: UNKNOWN ERROR!");
		return false;
	}

	/**Determines whether the board coordinate (x, y) is used in the game.
	   In most cases, all light spaces on the board will be considered illegal.
	   Also, any coordinate which does not exist is also considered illegal.
	   @param x The horizontal component of the coordinate.
	   @param y The vertical component of the coordinate.
	   @return True if the specified coordinate is nonexistant or unused in
	   the current rules. False if otherwise.
	*/
	public synchronized boolean isIllegalSpace(int x, int y) {
		return (
			x < 1
				|| x > iBoardSize
				|| y < 1
				|| y > iBoardSize
				|| (x - 1) % 2 != (y - 1) % 2);
	}

	/**Determines whether the board coordinate (x, y) is legally used in
	   the game.
	   @param x The horizontal component of the coordinate.
	   @param y The vertical component of the coordinate.
	   @return True if the specified coordinate is legal in the context of
	   the current rules. False if otherwise.
	*/
	public synchronized boolean isLegalSpace(int x, int y) {
		return !isIllegalSpace(x, y);
	}

	/**Determines whether a move from (x1, y1) to (x2, y2) is a legal slide.
	   Does not take into account the current turn state.
	   @param x1 The horizontal component of the coordinates containing
	   the piece to be tested.
	   @param y1 The vertical component of the coordinates containing the
	   piece to be tested.
	   @param x2 The horizontal component of the coordinates indicating the
	   prospective move.
	   @param y2 The vertical component of the coordinates indicating the
	   prospective move.
	   @return True if the specified slide is legal within the current rules.
	   False if otherwise.
	 */
	public synchronized boolean isLegalSlide(int x1, int y1, int x2, int y2) {
		if (isIllegalSpace(x1, y1) || isIllegalSpace(x2, y2))
			return false;
		if (isEmpty(x1, y1) || isOccupied(x2, y2))
			return false;
		if (isDark(x1, y1) || isKing(x1, y1)) {
			if (Math.abs(x2 - x1) == 1 && y2 == y1 + 1)
				return true;
		}
		if (isLight(x1, y1) || isKing(x1, y1)) {
			if (Math.abs(x2 - x1) == 1 && y2 == y1 - 1)
				return true;
		}
		return false;

	}

	/**Determines whether a move from (x1, y1) to (x2, y2) is a legal jump.
	   Does not take into account the current turn state.
	   @param x1 The horizontal component of the coordinates containing the
	   piece to be tested.
	   @param y1 The vertical component of the coordinates containing the
	   piece to be tested.
	   @param x2 The horizontal component of the coordinates indicating the
	   prospective move.
	   @param y2 The vertical component of the coordinates indicating the
	   prospective move.
	   @return True if the specified single jump is legal within the current rules.
	   False if otherwise.
	*/
	public synchronized boolean isLegalJump(int x1, int y1, int x2, int y2) {
		if (isIllegalSpace(x1, y1) || isIllegalSpace(x2, y2))
			return false;
		if (isEmpty(x1, y1) || isOccupied(x2, y2))
			return false;
		if (Math.abs(x2 - x1) != 2 || Math.abs(y2 - y1) != 2)
			return false;
		//If statements to work out which of 4 directions the jump is being made, and
		//if a piece of the right type exists to be jumped.
		int tTempX = x2 - x1;
		int tTempY = y2 - y1;
		//each value is either 2 or -2, indicating direction.
		if (tTempX == 2) {
			if (tTempY == 2) {
				//Check that the space between the coordinates is occupied.
				//Check that the occupying piece is a different colour to the jumping piece.
				//If these conditions are met, return true.
				if (isEmpty(x1 + 1, y1 + 1)
					|| isSameColour(x1, y1, x1 + 1, y1 + 1))
					return false;
				else
					return true;
			} else {
				if (isEmpty(x1 + 1, y1 - 1)
					|| isSameColour(x1, y1, x1 + 1, y1 - 1))
					return false;
				else
					return true;
			}
		}
		//Else -2:
		else {
			if (tTempY == 2) {
				if (isEmpty(x1 - 1, y1 + 1)
					|| isSameColour(x1, y1, x1 - 1, y1 + 1))
					return false;
				else
					return true;
			} else {
				if (isEmpty(x1 - 1, y1 - 1)
					|| isSameColour(x1, y1, x1 - 1, y1 - 1))
					return false;
				else
					return true;
			}
		}
	}

	/**Determines whether a move from (x1, y1, to (x2, y2) is legal.
	   @param x1 The horizontal component of the coordinates containing the
	   piece to be tested.
	   @param y1 The vertical component of the coordinates containing the
	   piece to be tested.
	   @param x2 The horizontal component of the coordinates indicating the
	   prospective move.
	   @param y2 The vertical component of the coordinates indicating the
	   prospective move.
	   @return True if the specified slide or jump is legal within the current rules.
	   False if otherwise.
	*/
	public synchronized boolean isLegalMove(int x1, int y1, int x2, int y2) {
		return (isLegalJump(x1, y1, x2, y2) || isLegalSlide(x1, y1, x2, y2));
	}

	/**Returns a List, possibly null, of coordinates that the next move
	   must select from. The coordinates are contained in java.awt.Point objects.
	   If this List contains Points, then one set of coordinates specified by
	   these Points must be used in the next move according to the current RuleSet,
	   and the move must be a jump. If the List is empty, the player
	   has free choice in which piece to move next.
	   @return A List, possibly empty, containing Point objects. Each Point object contains the coordinates of a piece on the board.
	*/
	public synchronized List mustJump() {
		if (debug)
			System.out.println(" Checking for pieces which MUST jump...");
		List tPieceList = new LinkedList();
		if (iMoveInProgress != null) {
			tPieceList.add(iMoveInProgress);
			return tPieceList;
		}

		for (int y = 1; y <= iBoardSize; y++) {
			for (int x = 1; x <= iBoardSize; x++) {
				if ((isLight(x, y) && isLightPlayerTurn())
					|| (isDark(x, y) && isDarkPlayerTurn())) {
					if (canJump(x, y))
						tPieceList.add(new Point(x, y));
				}
			}
		}

		if (debug)
			System.out.println(
				" Must jump check complete: " + tPieceList + " must jump.");
		return tPieceList;
	}

	/**Returns the number of light pieces left in play.
	   @return The number of light pieces left on the board.
	 */
	public synchronized int numberOfLightPieces() {
		int tCount = 0;
		for (int y = 0; y < iBoardSize; y++) {
			for (int x = 0; x < iBoardSize; x++) {
				if (iBoard[x][y] == 1 || iBoard[x][y] == 2)
					tCount++;
			}
		}
		return tCount;
	}

	/**Returns the number of dark pieces left in play.
	   @return The number of dark pieces left on the board.
	*/
	public synchronized int numberOfDarkPieces() {
		int tCount = 0;
		for (int y = 0; y < iBoardSize; y++) {
			for (int x = 0; x < iBoardSize; x++) {
				if (iBoard[x][y] == 3 || iBoard[x][y] == 4)
					tCount++;
			}
		}
		return tCount;
	}

	/**Main method for testing purposes only. Commented out.
	public static void main(String[] pArgs)
	{
	   new GameEngine(8);
	}*/

	//PRIVATE METHODS:   

	private boolean isSameColour(int x1, int y1, int x2, int y2) {
		if (isEmpty(x1, y1) || isEmpty(x2, y2))
			return false;
		return (
			(isLight(x1, y1) && isLight(x2, y2))
				|| (isDark(x1, y1) && isDark(x2, y2)));
	}

	//Private method for performing a slide. Makes no checks for legality.
	private void slide(int x1, int y1, int x2, int y2) {
		if (debug)
			System.out.print("Sliding...");
		iBoard[x2 - 1][y2 - 1] = iBoard[x1 - 1][y1 - 1];
		iBoard[x1 - 1][y1 - 1] = 0;
	}

	//Private method for performing a jump. Makes no checks for legality.
	private void jump(int x1, int y1, int x2, int y2) {
		if (debug)
			System.out.println("Attempting to jump...");
		iBoard[x2 - 1][y2 - 1] = iBoard[x1 - 1][y1 - 1];
		iBoard[x1 - 1][y1 - 1] = 0;

		//Locate the piece that has been jumped and remove it.
		int tTempX = x2 - x1;
		int tTempY = y2 - y1;
		//each value is either 2 or -2, indicating direction.
		if (tTempX == 2) {
			if (tTempY == 2) {
				iBoard[x1][y1] = 0;
			} else {
				iBoard[x1][y1 - 2] = 0;
			}
		}
		//Else -2:
		else {
			if (tTempY == 2) {
				iBoard[x1 - 2][y1] = 0;
			} else {
				iBoard[x1 - 2][y1 - 2] = 0;
			}
		}
	}

	private boolean darkCanMove() {
		for (int y = 1; y <= iBoardSize; y++) {
			for (int x = 1; x <= iBoardSize; x++) {
				if (isDark(x, y) && canMove(x, y))
					return true;
			}
		}
		return false;
	}

	private boolean lightCanMove() {
		for (int y = 1; y <= iBoardSize; y++) {
			for (int x = 1; x <= iBoardSize; x++) {
				if (isLight(x, y) && canMove(x, y))
					return true;
			}
		}
		return false;
	}

	/*True if the piece at the specified coordinate has been successfully crowned.
	 False if otherwise. Will only crown under correct board state conditions.*/
	private synchronized boolean crown(int x, int y) {
		try {
			if (isEmpty(x, y) || isKing(x, y) || isIllegalSpace(x, y))
				return false;
			if (isDark(x, y) && y == iBoardSize) {
				iBoard[x - 1][y - 1] = DARK_KING;
				if (debug)
					System.out.println(" Crown Successful.");
				return true;
			}

			if (isLight(x, y) && y == 1) {
				iBoard[x - 1][y - 1] = LIGHT_KING;
				if (debug)
					System.out.println(" Crown Successful.");
				return true;
			}
			return false;
		} catch (Exception e) {
			return false;
		}
	}
}
